package com.letv.so.servlet;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.letv.so.bean.AlbumBean;
import com.letv.so.bean.VideoBean;
import com.letv.so.constants.Constants;
import com.letv.so.util.SoKeyUtil;
import com.letv.so.util.StringUtil;

/**
 * cbase详情接口
 *
 * @author wenjian
 *
 */
public class QueryCbaseServlet extends AbstractQueryDataServlet {

	private static final long serialVersionUID = -2626713538347997214L;
	private static Logger logger = Logger.getLogger(QueryCbaseServlet.class);

	/**
	 * 查询专辑详情
	 */
	protected String query(Map<String, Object> rule) {
		long starttime = System.currentTimeMillis();
		String time = "";
		String reData = null;
		String sid = (String) rule.get("sid");
		String soKey = (String) rule.get("soKey");// 获得request sokey
		try {
			int videoListSize = (Integer) rule.get("videoListSize");// 获得request剧集列表个数
			int pn = (Integer) rule.get("pn");//
			int ps = (Integer) rule.get("ps");// 每页多少个
			String soData = queryDataService.get(sid,"inc"+soKey);// 获得cbase数据
			if (StringUtils.isBlank(soData)) {
				soData = queryDataService.get(sid,soKey);// 获得cbase数据
            }
			if (StringUtil.isBlank(soData)) {
				logger.warn("soKey:"+soKey+" get val from cbase为空!");
				return "{}";
			}
			//临时方案处理cmsimg数据,soKey=letv_cmsimg_0_0
			if (StringUtils.isNotBlank(soKey) && "newletv_cmsimg_0_0".equals(soKey)) {
				JSONArray jsonArray = JSONArray.parseArray(soData);
				int size = jsonArray.size();
				//pn默认为1，ps默认为50
				int fromIndex = pn * ps;
				int toIndex = (pn+1) * ps;
				List<Object> list = new ArrayList<Object>();
				if (toIndex<=size) {
					list = jsonArray.subList(fromIndex, toIndex);
                }else {
					if (fromIndex<size) {
						list = jsonArray.subList(fromIndex, size);
                    }
				}
				logger.info(sid+" ,soKey:letv_cmsimg_0_0 get val from cbase:"+list.size());
				return JSON.toJSONString(list);
            }

			int dataType = SoKeyUtil.getDataType(soKey);// 通过sokey意义，判断数据类型
			switch (dataType) {
			case Constants.ALBUM:
				AlbumBean album =null;
				try {
					album = JSON.parseObject(soData, AlbumBean.class);
				} catch (Exception e) {
					logger.error(sid+" ,parse album error", e);
				}
				if (album == null) {
					logger.warn(sid+ " ,soKey:"+soKey+" album==null ");
					return "{}";
				}
				if (videoListSize > 0 && (soKey.contains("newmms")||soKey.contains("new2mms"))) {// request要求有剧集列表，则封装
					time = setVideoList(sid, soKey, album, videoListSize,pn,ps,true);
				}
				reData = JSON.toJSONString(album, SerializerFeature.WriteTabAsSpecial);// 转为json格式
				break;
			case Constants.VIDEO:
				reData = soData;
				break;
			default:
				reData = soData;
				break;
			}
		} catch (Exception e) {
			logger.error(sid+" ,soKey:"+soKey+" error! return \"{}\"", e);
			return "{}";
		}
		logger.info(sid+",QueryCbaseServlet, total time=["+(System.currentTimeMillis()-starttime)+"],cbase time=["+time+"]");
		return reData;
	}

	private String getOrderlist(List<String> orders) {
		StringBuffer sb = new StringBuffer();
		int size = orders.size();
		for (int i = 0; i < size; i++) {
	        sb.append(orders.get(i));
	        if (i != size) {
	            sb.append(";");
            }
        }
		return sb.toString();
	}

	private String getTaglist(List<String> vidLists, int ps,List<String> orders) {
		StringBuffer tags = new StringBuffer();
		int count = 0;
		if (vidLists.size() != 0) {
			count = vidLists.size() / ps;
			if (vidLists.size() % ps != 0) {
				count ++;
            }

			tags.append("all:1-").append(count).append(":");
		}
		boolean beginZero = (orders.size() >0 && orders.get(0).equals("0"));
		int index = beginZero?(vidLists.size()-1):vidLists.size();
		int one = beginZero?1:0;
		int zero = beginZero?0:1;
		for (int i = 0; i < count; i++) {
			int start = zero + i * ps;
			int end =  ((i + 1) * ps)-one;
			if (index>=end) {
				tags.append(start).append("-").append(end);
	        } else {
	            if (index==start) {
	            	tags.append(start);
	            } else {
	                tags.append(start).append("-").append(index);
	            }
	         }
		     if (i!=count) {
		       tags.append(";");
	         }
	    }

		return tags.toString();
	}

	private String MD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        try {
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


	/**
	 * 封装剧集列表
	 *
	 * @param album
	 * @param videoListSize
	 */
	private String setVideoList(String sid, String soKey1, AlbumBean album, int videoListSize,int pn, int ps,boolean mmsFlag) {
		String time = "";
		long st1 = System.currentTimeMillis();
		String url = album.getUrl();
		String subSrc = album.getSubSrc();
		if (!StringUtil.isBlank(url) && (!StringUtil.isBlank(subSrc)) && ("nets".equals(subSrc) || "pan".endsWith(subSrc))) {
			int len = url.lastIndexOf('/') + 1;
			album.setPanid(url.substring(len));
			album.setSubSrc("nets");
        } else {
        	album.setPanid("");
        }
		String category = album.getCategory();
		List<VideoBean> videoList = new ArrayList<VideoBean>();
		List<String>  tags = new ArrayList<String>();
		List<String> videoTypes = new ArrayList<String>();
		String tagList = "";
		String orderList = "";
		try {
			if (Constants.SRC_VRS.equals(album.getSrc())) {// vrs专辑的剧集列表需要根据album.VidEpisode和.vids二次取cbase
				String aid = album.getAid();
				String idEpisodes = album.getVidEpisode();
				String vids = album.getVids();
				String ralbums = album.getSeriesAlbumIds();
				long s1 = System.currentTimeMillis();
				if(!StringUtils.isBlank(ralbums)){
					setRAlbum(ralbums,album);
				}
				logger.debug(sid+","+soKey1+",SRC_VRS setRAlbum cost time="+(System.currentTimeMillis()-s1));
				List<String> vidLists = new ArrayList<String>();
				List<String> orders = new ArrayList<String>();
				if (!StringUtil.isBlank(vids)) {
					String[] vidArray = vids.split(",");
					String[] idEpisodeArray = null;
					if (StringUtils.isNotBlank(idEpisodes)) {
						idEpisodeArray = idEpisodes.split(",");
                    } else {
                    	idEpisodeArray = new String[]{};
                    }
					// 电影电视剧动漫除外的频道视频列表倒序
					if (String.valueOf(Constants.MMS_MOVIE).equals(category) || String.valueOf(Constants.MMS_TV).equals(category) || String.valueOf(Constants.MMS_CARTOON).equals(category) || String.valueOf(Constants.MMS_OTHER).equals(category)) {
						vidArray = reverse1(vidArray);
					}else {
						idEpisodeArray = reverse1(idEpisodeArray);
					}
					long st2 = System.currentTimeMillis();
					logger.debug(sid+","+soKey1+",SRC_VRS setVideoList, cost time1=" + (st2-st1));
					List<String> allVidLists = Arrays.asList(vidArray);
					List<String> vidEpisodesLists = Arrays.asList(idEpisodeArray);
					logger.debug(sid+","+soKey1+" SRC_VRS vidEpisodesLists="+vidEpisodesLists+",size="+vidEpisodesLists.size());

					for (String vidEpisode : vidEpisodesLists) {//先添加正片vid
	                    int len = vidEpisode.indexOf("-");
	                    String vid = vidEpisode.substring(len+1);
	                    vidLists.add(vid);
	                    orders.add(vidEpisode.substring(0, len));//只有正片有order
                    }

					for (String vid : allVidLists) {//添加其他片vid
	                    if (!vidLists.contains(vid)) {
	                        vidLists.add(vid);
                        }
                    }

					int size = vidLists.size();
					logger.debug(sid+","+soKey1+" SRC_VRS retVids vidLists="+vidLists+",size="+size);
					//pn默认为1，ps默认为50
					ps = videoListSize > ps?ps:videoListSize;
					int fromIndex = pn * ps;
					int toIndex = (pn+1) * ps;
					List<String> retVids = new ArrayList<String>();
					if (toIndex<=size) {
						retVids = vidLists.subList(fromIndex, toIndex);
                    }else {
						if (fromIndex<size) {
							retVids = vidLists.subList(fromIndex, size);
                        }
					}
					logger.debug(sid+","+soKey1+",SRC_VRS retVids fromIndex="+fromIndex+",toIndex="+toIndex+",retVids.size="+retVids.size());
					List<String> soDataList = new ArrayList<String>();
					long st3 = System.currentTimeMillis();
					logger.debug(sid+","+soKey1+",SRC_VRS retVids, cost time2=" + (st3-st2));
					multiGetDataByIds(sid, soDataList, retVids, album.getSrc(), mmsFlag);
					long st34 = System.currentTimeMillis();
					time = (st34-st3)+",videolist="+retVids.size();
					logger.info(sid+" ,"+soKey1+",SRC_VRS retVids,from cbase total time=[" + (st34-st3)+"],videolist="+retVids.size());
					int i = 1;
					for (String soData : soDataList) {
						if (!StringUtil.isBlank(soData)) {
							VideoBean video = JSON.parseObject(soData, VideoBean.class);
							String videoType = video.getVideoType();
							if ((String.valueOf(Constants.TV).equals(category) || String.valueOf(Constants.CARTOON).equals(category))
									&& Constants.TYPE_ZHENGPIAN.equals(videoType)) {
								video.setUrl("http://www.letv.com/ptv/pplay/" + video.getAid() + "/" + i + ".html");
							} else {
								video.setUrl("http://www.letv.com/ptv/vplay/" + video.getVid() + ".html");
							}
							String videoUrl = video.getUrl();
							if (!StringUtil.isBlank(videoUrl)  && (!StringUtil.isBlank(subSrc)) && ("nets".equals(subSrc) || "pan".endsWith(subSrc))) {
								int len = videoUrl.lastIndexOf('/') + 1;
								video.setVideoPanid(videoUrl.substring(len));
					        } else {
					        	video.setVideoPanid("");
					        }
							if (StringUtils.isNotBlank(video.getPorder())) {
								videoTypes.add(video.getVideoType());
	                        }else {
	                        	videoTypes.add("null");
							}
							if (StringUtils.isNotBlank(video.getPorder())) {
								tags.add(video.getPorder());
	                        }else {
	                        	tags.add("null");
							}
							//每个视频添加唯一全局id
						    String porder = "1";
						    if (StringUtils.isNotBlank(video.getPorder())) {
						        porder = video.getPorder();
						    }
						    video.setGlobal_vid(aid+"_"+porder+"_"+MD5(video.getUrl()));
						    if (video != null) {
							    videoList.add(video);
						    }

						} else {
							tags.add("null");
						}
						i++;
					}
				}
				long st3 = System.currentTimeMillis();
				tagList = getTaglist(vidLists, ps,orders);
				orderList = getOrderlist(orders);
				logger.debug(sid+" ,"+soKey1+",SRC_VRS tagList&orderList cost time4=" + (System.currentTimeMillis()-st3));
			} else if (Constants.SRC_LESO.equals(album.getSrc())) {// leso专辑的剧集列表根据album.videoPlayUrls解析生成
				String videoPlayUrls = album.getVideoPlayUrls();
				 //死链map
				long st2 = System.currentTimeMillis();
				logger.debug(sid+" ,"+soKey1+",SRC_LESO deadlinkMap, cost time5=" + (st2-st1));
				if (!StringUtil.isBlank(videoPlayUrls)) {
					List<String> orders = new ArrayList<String>();
					String[] videoArray = videoPlayUrls.split(";");
					for (String vid : videoArray) {
						String[] videoFileds = vid.split("\\|");
						if (videoFileds.length==1) {//过滤不规范的数据
                            continue;
                        }
						orders.add(videoFileds[0]);
                    }
					List<String> vidLists = Arrays.asList(videoArray);
					//pn默认为0，ps默认为50
					ps = videoListSize > ps?ps:videoListSize;
					int size = vidLists.size();
					int fromIndex = pn * ps;
					int toIndex = (pn+1) * ps;
					List<String> retVids = new ArrayList<String>();
					List<String> retInfos = subList(fromIndex,toIndex,getList(album.getIntro()));
					List<String> subNames = subList(fromIndex,toIndex,getList(album.getVideoSubNames()));
					List<String> images = subList(fromIndex,toIndex,getList(album.getVideoImages()));
	                List<String> deadinfo = new ArrayList<String>();
	                List<String> uidInfo = new ArrayList<String>();
					if (fromIndex >= size) {
					    return time;
					} else if ( fromIndex<size && toIndex > size ) {
						    toIndex = size;
					}
		            ArrayList<String> deadlinkList = new ArrayList<String>();
		            String deadlinks = album.getDeadlinks();
		            convertStr2List(deadlinks,deadlinkList);
	                ArrayList<String> globalVids = new ArrayList<String>();
	                convertStr2List(album.getUnIds(),globalVids);
					retVids = vidLists.subList(fromIndex, toIndex);
					deadinfo = deadlinkList.subList(fromIndex, toIndex);
					uidInfo = globalVids.subList(fromIndex, toIndex);
					logger.info(sid+" ,"+soKey1+" SRC_LESO retVids fromIndex="+fromIndex+",toIndex="+toIndex+",videolist="+retVids.size());
					String aid = album.getAid();
					long st22 = System.currentTimeMillis();
					logger.debug(sid+" ,"+soKey1+",SRC_LESO videolist, cost time6=" + (st22-st2));
					for (int i=0;i<retVids.size();i++) {
						String vid = retVids.get(i);
						if (StringUtil.isNotBlank(vid)) {
							String[] videoFileds = vid.split("\\|");
							if (videoFileds.length==1) {//过滤不规范的数据
	                            continue;
                            }
							String[] videoInfo = retInfos.size() > i ? retInfos.get(i).split("\\|") : new String[0];
							String[] subName = subNames.size() > i ? subNames.get(i).split("\\|") : new String[0];
							String[] image = images.size() > i ? images.get(i).split("\\|") : new String[0];
							VideoBean video = new VideoBean();
							video.setDataType(Constants.VIDEO);
							video.setAorder(videoFileds[0]);
							video.setUrl(videoFileds[1]);
							video.setName(videoInfo.length > 1 ? videoInfo[1] : "");
							video.setSubName(subName.length > 1 ? subName[1] : video.getName());
							if (image.length > 1) {
							    try {
							        logger.error("images="+image[1]);
							        video.setImages(image[1]);
							    }catch(Exception e){
							        logger.error("parse images for single video,error album id="+album.getAid(),e);
							    }
							} 
							tags.add(videoFileds[0]);
							String videoUrl = video.getUrl();
							if (!StringUtil.isBlank(videoUrl)  && (!StringUtil.isBlank(subSrc)) && ("nets".equals(subSrc) || "pan".endsWith(subSrc))) {
								int len = videoUrl.lastIndexOf('/') + 1;
								video.setVideoPanid(videoUrl.substring(len));
					        } else {
					        	video.setVideoPanid("");
					        }
							//添加死链
							if (deadinfo.size() > i) {
								video.setDeadlink(deadinfo.get(i));
                            } else {
                            	logger.debug(sid+" ,"+soKey1+",SRC_LESO videoPlayUrls 与 deadlinks 不匹配 ");
                            	video.setDeadlink("0");
                            }
							//每个视频添加唯一全局id
							String porder = "1";
		                	if (StringUtils.isNotBlank(video.getAorder())) {
		                		porder = video.getAorder();
	                        }
		                	video.setGlobal_vid(aid+"_"+porder+"_"+MD5(video.getUrl()));
	                        if (uidInfo.size() > i) {
	                             video.setUnid(uidInfo.get(i));
	                        } else {
	                             logger.debug(sid+" ,"+soKey1+",SRC_LESO videoPlayUrls 与 uuids 不匹配 ");
	                             video.setUnid("");
	                        }
		                	videoList.add(video);
						} else {
							tags.add("null");
						}
                    }
					album.setSomePropertyNull();
					//album.setUnIds(null);
					logger.debug(sid+","+soKey1+",SRC_LESO videolist, cost time7=" + (System.currentTimeMillis()-st22));

					long st3 = System.currentTimeMillis();
					tagList = getTaglist(vidLists, ps,orders);
					orderList = getOrderlist(orders);
					logger.debug(sid+" ,"+soKey1+",SRC_LESO tagList, cost time8=" + (System.currentTimeMillis()-st3));
				}
			}
			if (videoList.size() > 0) {
				album.setVideoList(videoList);
				album.setTaglist(tagList);
				album.setOrderlist(orderList);
			}
		} catch (Exception e) {
			logger.error(sid+",exception: ",e);
		}
		return time;
	}

	private List<String> subList(int fromIndex, int toIndex,
            List<String> infoLists) {
        int size1 = infoLists.size();
        if (toIndex<=size1) {
            return infoLists.subList(fromIndex, toIndex);
        }else {
            if (fromIndex<size1) {
                return infoLists.subList(fromIndex, size1);
            }
        }
        return new ArrayList<String>();
    }

    private List<String> getList(String info) {
	    String[] infos =  StringUtil.isNotBlank(info) ? info.split(";") : new String[0];
        return Arrays.asList(info);
    }

    private void convertStr2List(String strs, ArrayList<String> list) {
        if (StringUtils.isNotBlank(strs)) {
            String[] strsArray = strs.split(";");
            if (null!=strsArray) {
                for (String str : strsArray) {
                    if (StringUtils.isNotBlank(str)) {
                        String[] dd = str.split("\\|");
                        if (dd.length==2) {
                            list.add(dd[1]);
                        }
                    }
                }
            }
        }
    }

	private void multiGetDataByIds(String sid, List<String> soDataList, List<String> retVids, String albumSrc, boolean mmsFlag) {
		String[] incsokeys = new String[retVids.size()];
		String[] sokeys = retVids.toArray(new String[retVids.size()]);
		String soKey =null;
		for (int i = 0;i< retVids.size();i++) {
			soKey = SoKeyUtil.getSoKey(albumSrc, Constants.VIDEO, retVids.get(i),mmsFlag);
			incsokeys[i] ="inc"+ soKey;
			sokeys[i] = soKey;
        }
		Map<String,Object> incData = queryDataService.getMulti(incsokeys);
		Map<String,Object> mdata = queryDataService.getMulti(sokeys);

		for (String key :incsokeys) {
			if (incData.get(key)!=null && !StringUtils.isBlank(incData.get(key).toString())) {
				soDataList.add(incData.get(key).toString());
	        } else {
	        	String tmpkey = key.substring(3);
				if (mdata.get(tmpkey) !=null && !StringUtils.isBlank(mdata.get(tmpkey).toString())) {
					soDataList.add(mdata.get(tmpkey).toString());
		        } else {
		        	logger.error(sid+" ,query cbase soKey=" + tmpkey + ", result is null");
		        }
	        }
		}

	}

	private void setRAlbum(String ids,AlbumBean album){

		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

			String[] albums = ids.split(",");
			for(String a:albums){
				if(!StringUtils.isBlank(a)){
					String albumStr = queryDataService.get("mms_vrs_a_"+a);// 获得cbase数据
					logger.debug("albumStr="+albumStr);
					AlbumBean abean =null;
					Map<String,Object> map = new HashMap<String,Object>();
					try {
						abean = JSON.parseObject(albumStr, AlbumBean.class);
					} catch (Exception e) {
						logger.error("parse album error", e);
					}
					if(null !=abean){
						map.put("aid", abean.getAid());
						map.put("name", abean.getName());
						map.put("images", abean.getImages());
					}
					list.add(map);
				}

			}

		album.setRelationAlbums(list);
	}

	private static String[] reverse1(String[] array) {
		String[] array1 = new String[array.length];
		int j=0;
		if(array.length>0){
			for (int i = array.length-1; i >=0 ; i--) {
				array1[j++]=array[i];
			}
			return array1;
		}
		return array;
	}

}
